package ru.ipo.dces.plugins.admin.components;

import info.clearthought.layout.TableLayout;
import ru.ipo.dces.client.Controller;
import ru.ipo.dces.client.messages.PopupMessageType;
import ru.ipo.dces.clientservercommunication.AcceptedResponse;
import ru.ipo.dces.clientservercommunication.ContestDescription;
import ru.ipo.dces.clientservercommunication.UserDataField;
import ru.ipo.dces.clientservercommunication.UserDescription;
import ru.ipo.dces.plugins.admin.UserTable;
import ru.ipo.dces.server.ServerFailReason;
import ru.ipo.dces.utils.ResponseHandler;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.HashSet;

public class ContestRegistrationPanel extends JPanel {

    private final RegistrationPanel registrationPanel;
    private JButton registrationButton;

    public UserTable getRegisterToContestTable() {
        return registrationPanel.getRegisterToContestTable();
    }

    public JButton getRegistrationButton() {
        return registrationButton;
    }

    public void setContest(ContestDescription contest) {
        registrationPanel.setContest(contest);
    }

    public ContestRegistrationPanel() {
        registrationPanel = new RegistrationPanel();
        registrationButton = new JButton("Регистрация");
        setLayout(new TableLayout(new double[]{TableLayout.FILL, TableLayout.PREFERRED, TableLayout.FILL},
                new double[]{TableLayout.FILL, TableLayout.PREFERRED, TableLayout.FILL}));
        add(registrationButton, "1, 1");
        addListeners();
        registrationPanel.hideAdminCheckBox();
        registrationPanel.removeAdminRights();
        registrationPanel.setRegisterToContestButtonText("Зарегистрироваться");
    }

    private void addListeners() {
        registrationButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                ContestRegistrationPanel.this.remove(registrationButton);
                repaint();
                add(registrationPanel, "0, 0, 2, 2");
                repaint();
                validate();
            }
        });
    }

    public void resetPanel() {
        registrationPanel.resetPanel();
        remove(registrationPanel);
        repaint();
        add(registrationButton, "1, 1");
        validate();
    }

    public static class RegistrationPanel extends JPanel {

        private final int separatorGap = 5;
        private JTextField loginRegisterEdit;
        private JPasswordField passwordRegisterEdit;
        private JPasswordField passwordRegisterEditRepeat;
        private UserTable registerToContestTable;
        private ContestDescription contestDescription;
        private JButton registerToContestButton;
        private JLabel messageLabel;
        private JCheckBox adminCheckBox;
        private boolean isAdmin = true;
        private HashSet<ActionListener> registrationListeners = new HashSet<ActionListener>();

        public RegistrationPanel() {
            setLayout(new TableLayout(
                    new double[]{separatorGap, TableLayout.PREFERRED, separatorGap, TableLayout.FILL, separatorGap},
                    new double[]{separatorGap, TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED,
                            separatorGap, TableLayout.FILL, TableLayout.PREFERRED, separatorGap, TableLayout.PREFERRED,
                            separatorGap}));
            add(new JLabel("Логин"), "1, 1");
            add(new JLabel("Пароль"), "1, 2");
            add(new JLabel("Повтор пароля"), "1, 3");

            loginRegisterEdit = new JTextField();
            passwordRegisterEdit = new JPasswordField();
            passwordRegisterEditRepeat = new JPasswordField();
            add(loginRegisterEdit, "3, 1");
            add(passwordRegisterEdit, "3, 2");
            add(passwordRegisterEditRepeat, "3, 3");

            registerToContestTable = new UserTable();
            registerToContestTable.putClientProperty("JTable.autoStartsEdit", Boolean.TRUE);
            registerToContestTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
            add(new JScrollPane(registerToContestTable), "1, 5, 3, 5");

            messageLabel = new JLabel("* - обязательно для заполнения");
            add(messageLabel, "1, 6, 3, 6");
            adminCheckBox = new JCheckBox("Админ.");
            add(adminCheckBox, "1, 8");
            registerToContestButton = new JButton("Зарегистрировать");
            add(registerToContestButton, "3, 8");
            addListeners();
        }

        private void addListeners() {
            registerToContestButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    if (contestDescription == null) return;

                    final String login = loginRegisterEdit.getText();
                    if (login.equals("")) {
                        JOptionPane.showMessageDialog(null, "Укажите логин для регистрации");
                        return;
                    }

                    if (JOptionPane.showConfirmDialog(
                            null,
                            "Подтвердите регистрацию участника с логином " + login,
                            "Регистрация",
                            JOptionPane.YES_NO_OPTION
                    ) == JOptionPane.NO_OPTION) return;

                    if (passwordRegisterEdit.getPassword().length == 0) {
                        JOptionPane.showMessageDialog(null, "Вы должны ввести пароль");
                        return;
                    }

                    if (passwordRegisterEditRepeat.getPassword().length == 0) {
                        JOptionPane.showMessageDialog(null, "Вы должны ввести подтверждение пароля");
                        return;
                    }

                    if (!Arrays.equals(passwordRegisterEdit.getPassword(), passwordRegisterEditRepeat.getPassword())) {
                        JOptionPane.showMessageDialog(null, "Пароль и подтверждение не совпадают");
                        return;
                    }

                    //get user data
                    final UserDataField[] contestData = contestDescription.data;
                    String[] userData = new String[contestData.length];
                    for (int i = 0; i < contestData.length; i++) {
                        if (contestData[i] == null)
                            continue;
                        userData[i] = registerToContestTable.getValue(i);
                        if (contestData[i].compulsory && userData[i].equals("") && !isAdmin) {
                            messageLabel.setForeground(Color.RED);
                            return;
                        }
                    }
                    UserDescription.UserType userType;
                    if (adminCheckBox.isSelected())
                        userType = UserDescription.UserType.ContestAdmin;
                    else
                        userType = UserDescription.UserType.Participant;

                    ResponseHandler<AcceptedResponse> handler = new ResponseHandler<AcceptedResponse>() {
                        @Override
                        public void success(AcceptedResponse response) {
                            for (ActionListener listener : registrationListeners)
                                listener.actionPerformed(new ActionEvent(this, 0, null));

                            //clear values
                            resetPanel();
                            registerToContestTable.setKeys(contestData);
                            Controller.showPopupMessage("Участник успешно зарегистрирован", PopupMessageType.Info);
                        }

                        @Override
                        public void fail(ServerFailReason exception) {
                        }
                    };
                    if (isAdmin)
                        Controller.addUser(login, passwordRegisterEdit.getPassword(), userData, userType,
                                contestDescription.contestID, handler);
                    else
                        Controller.registerAnonymouslyToContest(login, passwordRegisterEdit.getPassword(),
                                contestDescription.contestID, userData, handler);
                }
            });
        }

        public void resetPanel() {
            loginRegisterEdit.setText("");
            passwordRegisterEdit.setText("");
            passwordRegisterEditRepeat.setText("");
            messageLabel.setForeground(Color.black);
            adminCheckBox.setSelected(false);
        }

        public void setRegisterToContestButtonText(String text) {
            registerToContestButton.setText(text);
        }

        public void setContest(ContestDescription contest) {
            contestDescription = contest;
            if (contest == null)
                return;
            if (contest.data != null)
                registerToContestTable.setKeys(contest.data);
        }

        private void hideAdminCheckBox() {
            adminCheckBox.setVisible(false);
        }

        public UserTable getRegisterToContestTable() {
            return registerToContestTable;
        }

        public void addRegistrationListener(ActionListener l) {
            registrationListeners.add(l);
        }

        public void removeRegistrationListener(ActionListener l) {
            registrationListeners.remove(l);
        }

        private void removeAdminRights() {
            isAdmin = false;
        }
    }
}
